import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;


public class Player {
	
	int orderNum;
	private int vPts;
	int	roadNum;
	private int	armyNum;
	private int specialVPts;
	int rCardsNum;
	private Point temp;
	private int size;
	//Contains references to all roads, settlements, and cities (a city has a reference to both a city and a settlement
	private ArrayList<Building> buildings;
	private Hand hand;
	private int grain;
	private int lumber;
	private int ore;
	private int wool;
	private int brick;
	private SOCApplet applet;
	private PlayerView playerView;
	private Color color;
	private boolean hasLongRoad;
	private boolean hasLargeArmy;
	
	public Player (int orderNum, SOCApplet applet){
		this.orderNum = orderNum;
		buildings = new ArrayList<Building>();
		hand = new Hand(this, applet);
		this.applet = applet;
		armyNum = 0;
		vPts = 0;
		specialVPts = 0;
		this.playerView = new PlayerView(this, applet);
		//this is wrong for testing FIX IT LATER
		grain = 6;
		ore = 6;
		wool = 6;
		brick = 4;
		lumber = 4;
	}
	
	public int findLongestRoad(){
		ArrayList<Road> roads = getRoads();
		int largest = 1;
		while (roads.size() > 0){
			Road curr = roads.get(0);
			roads.remove(0);
			int temp = findChain(roads, curr.getP1()) + findChain(roads, curr.getP2());
//			int temp = findChain(roads, curr);
			if (temp > largest)
				largest = temp;
		}
		
		this.roadNum = largest - 1;
//		System.out.println("largest" + (largest - 1));
		return largest - 1;
	}
	
	public boolean checkLongest(){
		boolean isCurrLongest = true;
		for (Player p: applet.getPlayers()){
			if (p.findLongestRoad() > findLongestRoad()){
				isCurrLongest = false;
			}
		}
		if (findLongestRoad() < 5);
			isCurrLongest = false;
		if (isCurrLongest)
			setHasLongRoad(true);
		return isHasLongRoad();
	}
	
	private int findChain(ArrayList<Road> roads, Point p) {
		// TODO Auto-generated method stub
		int total = 0;
		int middle = 0;
		for (int i = 0; i < roads.size(); i++){
			if (p.isConnectedTo(roads.get(i))){
				Road temp = roads.remove(i);
				Point pTemp = null;
				if (temp.getP1() == p){
					pTemp = temp.getP2();
				} else 
					pTemp = temp.getP1();
				middle = findChain(roads, pTemp);
//				System.out.println("middle" + middle);
				if (middle > total)
					total += middle;
			}
		}
//		System.out.println("total" + total);
		return 1 + total;
	}
	
	public void setColor(Color color){
		this.color = color;
	}
	
	public Color getColor(){
		return color;
	}
	
	public int countVPts(){
		int SetPts = getSettlements().size();
		int CitPts = getCities().size();
		int total = SetPts + CitPts;
		if (hasLargeArmy())
			total += 2;
		if (checkLongest())
			total += 2;
		vPts = total;
		return total;
	}

	public boolean hasLargeArmy() {
		// TODO Auto-generated method stub
		boolean currLargest = true;
		
		for (Player p: applet.getPlayers()){
			if (p.armyNum > armyNum)
				currLargest = false;
		}
		if (armyNum < 3)
			currLargest = false;
		if (currLargest)
			hasLargeArmy = true;
		return false;
	}

	public int findChain (ArrayList<Road> roads, Road curr){
		int total = 1;
		int middle = 0;
		for (int i = 0; i< roads.size(); i++){
			Road r = roads.get(i);
			if (curr.isConnectedTo(r)){
				roads.remove(r);
				int temporary = findChain(roads, r);
				if (temporary > middle)
					middle = temporary;
			}
		}
		total += middle;
		return total;
	}
	
	
	/*
	 * addResource commands add @param int to various resources.
	 */
	public ArrayList<Building> getBuildings(){
		return buildings;
	}
	public int getGrain() {
		return grain;
	}
	public void addGrain(int grain) {
		this.grain += grain;
	}
	public int getLumber() {
		return lumber;
	}
	public void addLumber(int lumber) {
		this.lumber += lumber;
	}
	public int getOre() {
		return ore;
	}
	public void addOre(int ore) {
		this.ore += ore;
	}
	public int getWool() {
		return wool;
	}
	public void addWool(int wool) {
		this.wool += wool;
	}
	public int getBrick() {
		return brick;
	}
	public void addBrick(int brick) {
		this.brick += brick;
	}
	public int getRCards(){
		return brick + grain + lumber + ore + wool;
	}
	
	public boolean drawSCard(){
		if(ore >= 1 && wool >= 1 && grain >= 1){
			addOre(-1);
			addWool(-1);
			addGrain(-1);
			int temp = (int) (Math.random() * 25);
			int numCards = hand.getCards().size();
			if (temp <= 13)
				hand.addSCard(new KnightCard(this.hand, 420 + 40 * numCards, 640, 40, 40));
			else if (temp <= 15)
				hand.addSCard(new InventionCard(this.hand, 420 + 40 * numCards, 640, 40, 40));
			else if (temp <= 17)
				hand.addSCard(new MonopolyCard(this.hand, 420 + 40 * numCards, 640, 40, 40));
			else if (temp <= 22)
				hand.addSCard(new VictoryPointCard(this.hand, 420 + 40 * numCards, 640, 40, 40));
			else
				hand.addSCard(new RoadBuildCard(this.hand, 420 + 40 * numCards, 640, 40, 40));
			return true;
		}
		return false;
	}
	
	//Builds first point of a road
	public void startRoad(Point p){
		this.temp = p;
	}
	public boolean endRoad(Point p){
		if (temp != null && isValidEndLocation(p)){
			if (!applet.getTurn().isFreeRoad()){
				if(brick >= 1 && lumber >= 1){
					buildings.add(new Road(temp, p, this));
					temp = null;
					addBrick(-1);
					addLumber(-1);
				}
			}else {
				buildings.add(new Road(temp, p, this));
				temp = null;
				applet.getTurn().toggleFreeRoad(false);
			}
			return true;
		} else {
			temp = p;
			return false;
		}
	}
	
	public boolean endFreeRoad(Point p){
		if (temp != null && isValidEndLocation(p)){
			buildings.add(new Road(temp, p, this));
			temp = null;
			return true;
		} else {
			temp = p;
			return false;
		}
	}
	
	public boolean isValidEndLocation(Point p) {
		/*Checks that p is adjacent to temp and that p is connected to at least one other road owned by the same player
		*If there are fewer than two roads owned by the player then it does not need to be connected
		* Precondition: Point temp exists.
		*/
		if (p.isAdjacentTo(temp)){
			ArrayList<Road> roads = new ArrayList<Road>();
			for (Building b: buildings){
				if (b instanceof Road)
					roads.add((Road)b);
			}
			if (roads.size() < 2)
				return true;
			else if (p.isConnectedTo(roads)){
				return true;
			}
		}
		return false;
	}
	
	public int getKnightNum(){
		return armyNum;
	}
	
	public void addKnight(){
		armyNum ++;
	}
	
	public void addBuilding(Building b){
		buildings.add(b);
	}
	
	public int getSettlementsNum(){
		return getSettlements().size();
	}
	
	public int getCitiesNum(){
		return getCities().size();
	}
	public int getvPts() {
		return vPts;
	}
	public void setvPts(int vPts) {
		this.vPts = vPts;
	}
	public int getArmyNum() {
		return armyNum;
	}
	public void setArmyNum(int armyNum) {
		this.armyNum = armyNum;
	}
	
	public ArrayList<Settlement> getSettlements(){
		ArrayList<Settlement> settlements = new ArrayList<Settlement>();
		for(Building b: buildings){
			if(b instanceof Settlement){
				settlements.add((Settlement)b);
			}
		}
		return settlements;
	}
	
	public ArrayList<City> getCities(){
		ArrayList<City> cities = new ArrayList<City>();
		for(Building b: buildings){
			if(b instanceof City){
				cities.add((City)b);
			}
		}
		return cities;
	}
	public Hand getHand(){
		return hand;
	}
	public void setSpecialVPts(int specialVPts) {
		this.specialVPts = specialVPts;
	}
	public int getSpecialVPts() {
		return specialVPts;
	}
	public ArrayList<Road> getRoads() {
		ArrayList<Road> roads = new ArrayList<Road>();
		for (Building b: buildings){
			if (b instanceof Road)
				roads.add((Road) b);
		}
		return roads;
	}
	public PlayerView getPlayerView() {
		// TODO Auto-generated method stub
		return playerView;
	}

	public void setHasLongRoad(boolean hasLongRoad) {
		this.hasLongRoad = hasLongRoad;
	}

	public boolean isHasLongRoad() {
		return hasLongRoad;
	}

	public boolean isHasLargeArmy() {
		return hasLargeArmy;
	}

	public void setHasLargeArmy(boolean hasLargeArmy) {
		this.hasLargeArmy = hasLargeArmy;
	}

}
